#include "include/lib.h"
#include "include/cxxstd.h"
#include "include/corba.h"

namespace zero
{
static POA poa;

POA* ORB::allocPOA()
{
	return &poa;
}
EXPORT_CXX_TEXT(_ZN4zero3ORB8allocPOAEv);

void ORB::registerServerObject(const char* ifName, ServerObject* so, void* ifEntry)
{
	pool[0].ifName = ifName;
	pool[0].so = so;
	pool[0].ifEntry = ifEntry;
}

void* ORB::query(const char* ifName, ServerObject** so, CalleeLocation* cl, void* stub)
{
	*so = pool[0].so;
	*cl = LOCAL_HOST;
	if (*cl == IN_PROCESS)
		return pool[0].ifEntry;
	else
		return stub;
}
EXPORT_CXX_TEXT(_ZN4zero3ORB5queryEPKcPPNS_12ServerObjectEPNS_14CalleeLocationEPv);

static char inBuf[256];
static char outBuf[256];

void ORB::invokeAsyn(StaticRequest& sr, Object& from, ServerObject& to, CalleeLocation cl)
{
	int index = 0, inLen = 0, outLen = 0; StaticAny *sa = NULL, *res = sr.getResult();
	if (res != NULL)
		outLen += res->getSTI()->getLength();
	while ((sa = sr.iterator(index++)) != NULL) {
		if ((sa->getFlag() & StaticAny::ARGUMENT_IN) == StaticAny::ARGUMENT_IN)
			inLen += sa->getSTI()->getLength();
		if ((sa->getFlag() & StaticAny::ARGUMENT_OUT) == StaticAny::ARGUMENT_OUT)
			outLen += sa->getSTI()->getLength();
	}

	assert(inLen <= 256); assert(outLen <= 256);
	DataEncoder* de = new DataEncoder(inBuf); DataDecoder* dd = new DataDecoder(outBuf);
	sr.setDataEncoder(de); sr.setDataDecoder(dd);
	index = 0;
	while ((sa = sr.iterator(index++)) != NULL) {
		if ((sa->getFlag() & StaticAny::ARGUMENT_IN) == StaticAny::ARGUMENT_IN)
			sa->getSTI()->marshal(*de, sa->getValue());
	}

	// call to server.
	StaticServerRequest ssr(sr.getOpName());
	DataEncoder sde(outBuf); DataDecoder sdd(inBuf);
	ssr.setDataEncoder(&sde); ssr.setDataDecoder(&sdd);
	to.invoke(ssr);

	// return to client.
	DataEncoder::HeaderFlag hf = dd->getHeader(); 
	if (hf != DataEncoder::NORMAL) {
		sr.setException(reinterpret_cast<StaticAny*>(hf));
	} else {
		index = 0;
		if (res != NULL)
			res->getSTI()->demarshal(*dd, res->getValue());
		while ((sa = sr.iterator(index++)) != NULL) {
			if ((sa->getFlag() & StaticAny::ARGUMENT_OUT) == StaticAny::ARGUMENT_OUT)
				sa->getSTI()->demarshal(*dd, sa->getValue());
		}
	}
}
EXPORT_CXX_TEXT(_ZN4zero3ORB10invokeAsynERNS_13StaticRequestERNS_6ObjectERNS_12ServerObjectENS_14CalleeLocationE);

int ORB::maybeThrow(StaticRequest& sr, ...)
{
	DataDecoder* dd = sr.getDataDecoder();
	DataEncoder* de = sr.getDataEncoder();
	int order = reinterpret_cast<int>(sr.getException());
	if (order != 0) {
		va_list ap;
		va_start(ap, sr);
		while (va_arg(ap, int) != order)
			va_arg(ap, StaticTypeInfo*);
		StaticTypeInfo* ex = va_arg(ap, StaticTypeInfo*);
		ex->demarshal(*dd, NULL);
		va_end(ap);
	}
	delete dd; delete de;
	return order;
}
EXPORT_CXX_TEXT(_ZN4zero3ORB10maybeThrowERNS_13StaticRequestEz);

void ORB::dealWithArgs(StaticServerRequest& ssr)
{
	int index = 0; StaticAny *sa = NULL;
	while ((sa = ssr.iterator(index++)) != NULL) {
		if ((sa->getFlag() & StaticAny::ARGUMENT_IN) == StaticAny::ARGUMENT_IN)
			sa->getSTI()->demarshal(*ssr.getDataDecoder(), sa->getValue());
	}
}

void ORB::writeResults(StaticServerRequest& ssr)
{
	int index = 0; StaticAny *sa = NULL, *res = ssr.getResult();
	DataEncoder& de = *ssr.getDataEncoder();
	de.setHeader(DataEncoder::NORMAL);
	if (res != NULL)
		res->getSTI()->marshal(de, res->getValue());
	while ((sa = ssr.iterator(index++)) != NULL) {
		if ((sa->getFlag() & StaticAny::ARGUMENT_OUT) == StaticAny::ARGUMENT_OUT)
			sa->getSTI()->marshal(de, sa->getValue());
	}
}

void ORB::writeException(StaticServerRequest& ssr, int order)
{
	DataEncoder& de = *ssr.getDataEncoder();
	de.setHeader((DataEncoder::HeaderFlag) order);
	StaticAny *ex = ssr.getException();
	ex->getSTI()->marshal(de, NULL);
}
}
// vim: foldmarker=<([{,}])> foldmethod=marker
